#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cerrno>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <functional>
#include <signal.h>
#include "logMessage.hpp"
#include "protocal.hpp"
#define SEP " "
#define SEP_LEN strlen(SEP)
using namespace std;

static const uint16_t gport = 8080;
static const int gbacklog = 5;
typedef function<bool(const Request &req, Resposne &res)> func_t;
void HanderEntery(int sock,func_t func)
{
    string inbuffer;
    while(1)
    {
        //1.读取
        //1.1 怎么读取
        string req_str;
        //2.对请求request进行反序列化
        Request req;
        if(!recvRequest(sock,inbuffer,&req_str))
        return;
        string req_text;
        if(!delength(req_str,&req_text))
        return;
        if(!req.deserialization(req_text)) 
        return;
        //2.1 得到一个结构化的请求对象
        Resposne res;
        //3.计算机处理----业务逻辑
        func(req,res);
        cout<<"exitcode :"<<res._exitcode<<endl;
        cout<<"result :"<<res._result<<endl;
        //3.1得到一个结构化的响应
        string res_text;
        //4.对响应response进行序列化
        res.serialization(&res_text);
        string send_message = enlength(res_text);
        //5.发送响应
        send(sock,send_message.c_str(),send_message.size(),0);
    }
}
bool calculate(const Request &req, Resposne &res)
{
    int x = req._x;
    int y = req._y;
    char op = req._op;
    switch(op)
    {
        case '+':
        {
            res._exitcode = 0;
            res._result = x+y;
            return true;
        }
        case '-':
        {
            res._exitcode = 0;
            res._result = x-y;
            return true;
        }
        case '*':
        {
            res._exitcode = 0;
            res._result = x*y;
            return true;
        }
        case '/':
        {
            if(y == 0)
            {
                res._exitcode = 1;
                cout<<"除零错误"<<endl;
                return false;
            }
            else
            {
                res._exitcode = 0;
                res._result = x/y;
            }
            return true;
        }
        case '%':
        {
            if(y == 0)
            {
                res._exitcode = 1;
                cout<<"模零错误"<<endl;
                return false;
            }
            else
            {
                res._exitcode = 0;
                res._result = x%y;
            }
            return true;
        }

    }
}

class CalServer
{

public:
    CalServer(const uint16_t &port = gport) : _port(port)
    {}
    ~CalServer()
    {}
    void Init()
    {
        // 创建套接字
        _socketfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_socketfd < 0)
        {
            logMessage(ERROR, "socket create error errno : %d",errno);
            exit(2);
        }
        logMessage(NORMAL,"socket success");
        // bind
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_socketfd, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            logMessage(ERROR, "bind error  errno : %d",errno);
            cerr << strerror(errno) << endl;
            exit(2);
        }
        logMessage(NORMAL, "bind success");
        // lisen
        _listenfd = listen(_socketfd, gbacklog);
        if (_listenfd < 0)
        {
            logMessage(ERROR, "listen error errno : %d",errno);
            exit(2);
        }
        logMessage(NORMAL, "listen success");
    }
    
    void start()
    {
        //对子进程返回信号无视
        //signal(SIGCHLD,SIG_IGN);
        while (1)
        {
            // 建立新连接
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sock = accept(_socketfd, (struct sockaddr *)&peer, &len);
            // 未来通信就使用sock，后续为文件操作
            if (sock < 0)
            {
                logMessage(ERROR, "accept error  errno : %d",errno);
                exit(2);
            }
            logMessage(NORMAL, "accept success");
            // Verson 2多进程版
            pid_t id = fork();
            if (id == 0)
            {
                close(_listenfd); // 子进程不需要监听，防止误操作
                if(fork()>0)exit(0);//创建孙子进程进行后续操作，子进程直接退出，孙子进程完成任务会被当作孤儿进程回收
                HanderEntery(sock,calculate);
                close(sock);
                exit(0);
            }
            //father
            close(sock);  
        }
    }

private:
    int _socketfd;
    int _listenfd;
    uint16_t _port;
};
